package com.oa.kq.ctrl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.audit.log.client.annotation.AuditLog;
import com.mdp.audit.log.client.annotation.OperType;
import com.mdp.core.entity.LangTips;
import com.mdp.core.entity.Result;
import com.mdp.core.entity.Tips;
import com.mdp.core.query.QueryTools;
import com.mdp.core.utils.BaseUtils;
import com.mdp.core.utils.NumberUtil;
import com.mdp.core.utils.RequestUtils;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import com.mdp.swagger.ApiEntityParams;
import com.oa.common.entity.UserBaseInfo;
import com.oa.common.service.UserBaseInfoService;
import com.oa.kq.entity.EmpVacationInfo;
import com.oa.kq.entity.VacationType;
import com.oa.kq.service.EmpVacationInfoService;
import com.oa.kq.service.VacationTypeService;
import com.oa.kq.service.VacationTypeUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author maimeng-mdp code-gen
 * @since 2023年10月9日
 */
@RestController
@RequestMapping(value = "/*/oa/kq/empVacationInfo")
@Api(tags = {"员工请假信息表-操作接口"})
public class EmpVacationInfoController {

    static Logger logger = LoggerFactory.getLogger(EmpVacationInfoController.class);

    @Autowired
    private EmpVacationInfoService empVacationInfoService;
    @Autowired
    private VacationTypeUserService vacationTypeUserService;

    @Autowired
    private UserBaseInfoService hrUserBaseInfoService;

    @Autowired
    private VacationTypeService vacationTypeService;

    @ApiOperation(value = "员工请假信息表-查询列表", notes = " ")
    @ApiEntityParams(EmpVacationInfo.class)
    @ApiResponses({@ApiResponse(code = 200, response = EmpVacationInfo.class, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'错误码'},total:总记录数,data:[数据对象1,数据对象2,...]}")})
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public Result listEmpVacationInfo(@ApiIgnore @RequestParam Map<String, Object> params) {
        User user = LoginUtils.getCurrentUserInfo();
        RequestUtils.transformArray(params, "ids");
        RequestUtils.transformArray(params, "deptids");
        QueryWrapper<EmpVacationInfo> qw = QueryTools.initQueryWrapper(EmpVacationInfo.class, params);
        IPage page = QueryTools.initPage(params);
        List<Map<String, Object>> datas = empVacationInfoService.selectListMapByWhere(page, qw, params);
        return Result.ok("query-ok", "查询成功").setData(datas).setTotal(page.getTotal());
    }

    /**
     * 员工假期统计
     *
     * @param kqEmpVacationInfo
     * @return
     */
    @RequestMapping(value = "/empVacationCalc", method = RequestMethod.GET)
    public Result empVacationCalc(@RequestParam Map<String, Object> kqEmpVacationInfo) {
        User user = LoginUtils.getCurrentUserInfo();
        kqEmpVacationInfo.put("branchId", user.getBranchId());
        String year = (String) kqEmpVacationInfo.get("year");
        if (!StringUtils.hasText(year)) {
            return Result.error("year-null", "年份参数不能为空");
        }
        Map<String, Object> m = new HashMap<>();
        RequestUtils.transformArray(kqEmpVacationInfo, "deptids");
        QueryWrapper<EmpVacationInfo> qw = QueryTools.initQueryWrapper(EmpVacationInfo.class, kqEmpVacationInfo);
        IPage page = QueryTools.initPage(kqEmpVacationInfo);
        List<Map<String, Object>> hrUserBaseInfos = hrUserBaseInfoService.selectListMapByWhere(page, qw, kqEmpVacationInfo);
        VacationType typeQuery = new VacationType();
        typeQuery.setBranchId(user.getBranchId());
        List<VacationType> kqVacationTypes = this.vacationTypeService.selectListByWhere(typeQuery);

        if (hrUserBaseInfos != null && hrUserBaseInfos.size() > 0) {
            BigDecimal totalHours = BigDecimal.ZERO;
            for (VacationType kqVacationType : kqVacationTypes) {
                totalHours = totalHours.add(kqVacationType.getTotalHours());
            }
            List<String> userids = hrUserBaseInfos.stream().map(i -> (String) i.get("userid")).collect(Collectors.toList());
            kqEmpVacationInfo.put("userids", userids);
            List<Map<String, Object>> kqEmpVacationInfoList = empVacationInfoService.selectListMapByWhere(page, qw, kqEmpVacationInfo);
            Map<String, BigDecimal> userVacations = new HashMap<>();
            for (Map<String, Object> vacation : kqEmpVacationInfoList) {
                String userid = (String) vacation.get("userid");
                String vacationId = (String) vacation.get("vacationId");
                String key = userid + "_" + vacationId;
                BigDecimal number = NumberUtil.getBigDecimal(userVacations.get(key));
                if (number == null) {
                    number = BigDecimal.ZERO;
                    userVacations.put(key, BigDecimal.ZERO);
                }
                BigDecimal userNumber = NumberUtil.getBigDecimal(vacation.get("vacationHours"), BigDecimal.ZERO);
                number = number.add(userNumber);
                userVacations.put(key, number);
            }
            for (Map<String, Object> hrUserBaseInfo : hrUserBaseInfos) {
                String userid = (String) hrUserBaseInfo.get("userid");
                UserBaseInfo userObj = BaseUtils.fromMap(hrUserBaseInfo, UserBaseInfo.class);
                BigDecimal canHours = BigDecimal.ZERO;
                BigDecimal initHours = BigDecimal.ZERO;
                BigDecimal usedHours = BigDecimal.ZERO;
                for (VacationType kqVacationType : kqVacationTypes) {
                    BigDecimal empCanHours = vacationTypeService.calcEmpEffectHours(kqVacationType, userObj, NumberUtil.getInteger(year));
                    canHours = canHours.add(empCanHours);
                    initHours = initHours.add(kqVacationType.getTotalHours());
                    String key = userid + "_" + kqVacationType.getId();
                    BigDecimal typeUsedHours = NumberUtil.getBigDecimal(userVacations.get(key), BigDecimal.ZERO);
                    usedHours = usedHours.add(typeUsedHours);
                    hrUserBaseInfo.put("canHours_" + kqVacationType.getId(), empCanHours);
                    hrUserBaseInfo.put("initHours_" + kqVacationType.getId(), kqVacationType.getTotalHours());
                    hrUserBaseInfo.put("usedHours_" + kqVacationType.getId(), typeUsedHours);
                }
                hrUserBaseInfo.put("canHours", canHours);
                hrUserBaseInfo.put("initHours", initHours);
                hrUserBaseInfo.put("usedHours", usedHours);
            }
        }
        return Result.ok("查询成功").setData(hrUserBaseInfos);
    }

    @ApiOperation(value = "员工请假信息表-新增", notes = " ")
    @ApiResponses({@ApiResponse(code = 200, response = EmpVacationInfo.class, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'},data:数据对象}")})
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public Result addEmpVacationInfo(@RequestBody EmpVacationInfo empVacationInfo) {
        if (StringUtils.isEmpty(empVacationInfo.getId())) {
            empVacationInfo.setId(empVacationInfoService.createKey("id"));
        } else {
            EmpVacationInfo kqEmpVacationInfoQuery = new EmpVacationInfo(empVacationInfo.getId());
            if (empVacationInfoService.countByWhere(kqEmpVacationInfoQuery) > 0) {
                return Result.error("编号重复，请修改编号再提交");
            }
        }
        String bizFlowState = empVacationInfo.getBizFlowState();
        if (!StringUtils.hasText(bizFlowState)) {
            empVacationInfo.setBizFlowState("0");
        }
        empVacationInfoService.insert(empVacationInfo);
        return Result.ok("add-ok", "添加成功！").setData(empVacationInfo);
    }

    @ApiOperation(value = "员工请假信息表-删除", notes = " ")
    @ApiResponses({@ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}}")})
    @RequestMapping(value = "/del", method = RequestMethod.POST)
    public Result delEmpVacationInfo(@RequestBody EmpVacationInfo empVacationInfo) {
        empVacationInfoService.deleteByPk(empVacationInfo);
        return Result.ok("del-ok", "删除成功！");
    }

    @ApiOperation(value = "员工请假信息表-修改", notes = " ")
    @ApiResponses({@ApiResponse(code = 200, response = EmpVacationInfo.class, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'},data:数据对象}")})
    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    public Result editEmpVacationInfo(@RequestBody EmpVacationInfo empVacationInfo) {
        empVacationInfoService.updateByPk(empVacationInfo);
        return Result.ok("edit-ok", "修改成功！").setData(empVacationInfo);
    }

    @ApiOperation(value = "员工请假信息表-批量修改某些字段", notes = "")
    @ApiEntityParams(value = EmpVacationInfo.class, props = {}, remark = "员工请假信息表", paramType = "body")
    @ApiResponses({@ApiResponse(code = 200, response = EmpVacationInfo.class, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'},data:数据对象}")})
    @RequestMapping(value = "/editSomeFields", method = RequestMethod.POST)
    public Result editSomeFields(@ApiIgnore @RequestBody Map<String, Object> params) {
        User user = LoginUtils.getCurrentUserInfo();
        empVacationInfoService.editSomeFields(params);
        return Result.ok("edit-ok", "更新成功");
    }

    /**
     * 流程审批过程中回调该接口，更新业务数据
     * 如果发起流程时上送了restUrl，则无论流程中是否配置了监听器都会在流程发生以下事件时推送数据过来
     * eventName: PROCESS_STARTED 流程启动完成 全局
     * PROCESS_COMPLETED 流程正常结束 全局
     * PROCESS_CANCELLED 流程删除 全局
     * create 人工任务启动
     * complete 人工任务完成
     * assignment 人工任务分配给了具体的人
     * delete 人工任务被删除
     * <p>
     * 其中 create/complete/assignment/delete事件是需要在模型中人工节点上配置了委托代理表达式 ${taskBizCallListener}才会推送过来。
     * 在人工任务节点上配置 任务监听器  建议事件为 complete,其它assignment/create/complete/delete也可以，一般建议在complete,委托代理表达式 ${taskBizCallListener}
     *
     * @param flowVars {flowBranchId,agree,procInstId,assignee,actId,taskName,mainTitle,branchId,bizKey,commentMsg,eventName,modelKey} 等
     * @return 如果tips.isOk==false，将影响流程提交
     **/
    @AuditLog(firstMenu = "办公平台", secondMenu = "请假申请", func = "processApprova", funcDesc = "请假审核流程", operType = OperType.UPDATE)
    @RequestMapping(value = "/processApprova", method = RequestMethod.POST)
    public Result processApprova(@RequestBody Map<String, Object> flowVars) {
        Map<String, Object> m = new HashMap<>();
        Tips tips = new Tips("成功新增一条数据");
        QueryWrapper<EmpVacationInfo> qw = QueryTools.initQueryWrapper(EmpVacationInfo.class, flowVars);
        IPage page = QueryTools.initPage(flowVars);
        this.empVacationInfoService.processApprova(page, qw, flowVars);
        return Result.ok("成功新增一条数据");
    }


    @ApiOperation(value = "员工请假信息表-批量删除", notes = " ")
    @ApiResponses({@ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}")})
    @RequestMapping(value = "/batchDel", method = RequestMethod.POST)
    public Result batchDelEmpVacationInfo(@RequestBody List<EmpVacationInfo> empVacationInfos) {
        User user = LoginUtils.getCurrentUserInfo();
        if (empVacationInfos.size() <= 0) {
            return Result.error("batchDel-data-err-0", "请上送待删除数据列表");
        }
        List<EmpVacationInfo> datasDb = empVacationInfoService.listByIds(empVacationInfos.stream().map(i -> i.getId()).collect(Collectors.toList()));

        List<EmpVacationInfo> can = new ArrayList<>();
        List<EmpVacationInfo> no = new ArrayList<>();
        for (EmpVacationInfo data : datasDb) {
            if (true) {
                can.add(data);
            } else {
                no.add(data);
            }
        }
        List<String> msgs = new ArrayList<>();
        if (can.size() > 0) {
            empVacationInfoService.removeByIds(can);
            msgs.add(LangTips.transMsg("del-ok-num", "成功删除%s条数据.", can.size()));
        }

        if (no.size() > 0) {
            msgs.add(LangTips.transMsg("not-allow-del-num", "以下%s条数据不能删除:【%s】", no.size(), no.stream().map(i -> i.getId()).collect(Collectors.joining(","))));
        }
        if (can.size() > 0) {
            return Result.ok(msgs.stream().collect(Collectors.joining()));
        } else {
            return Result.error(msgs.stream().collect(Collectors.joining()));
        }
    }

    @ApiOperation(value = "员工请假信息表-根据主键查询一条数据", notes = " ")
    @ApiResponses({@ApiResponse(code = 200, response = EmpVacationInfo.class, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'},data:数据对象}")})
    @RequestMapping(value = "/queryById", method = RequestMethod.GET)
    public Result queryById(EmpVacationInfo empVacationInfo) {
        EmpVacationInfo data = (EmpVacationInfo) empVacationInfoService.getById(empVacationInfo);
        return Result.ok().setData(data);
    }

}
